%{

extern int lineno;
extern bool fileEnd;

#include "ast.h"
#include "lex.yy.c"
#include <vector>

/* parse error */
void yyerror ( char* s ) {
    printf("*** %s (line : %d, token: %s)\n", s, lineno, yytext);
};

%}
%union {
        char*           Tstring;
        ast*            Tast;
        ast_list*       Tast_list;

        int intConst;
        double doubleConst;
        char* stringConst;
}

%token <Tstring> SYMBOL_LPAREN SYMBOL_RPAREN SYMBOL_LBRACKET SYMBOL_RBRACKET SYMBOL_LBRACE SYMBOL_RBRACE
       SYMBOL_COLON SYMBOL_DOT SYMBOL_SEMICOLON SYMBOL_COMMA SYMBOL_ASSIGN
	   SYMBOL_PLUS SYMBOL_MINUS SYMBOL_STAR SYMBOL_SLASH SYMBOL_BACKSLASH
	   SYMBOL_EQ SYMBOL_NEQ SYMBOL_LT SYMBOL_LE SYMBOL_GT SYMBOL_GE
	   SYMBOL_LABRACKET SYMBOL_RABRACKET SYMBOL_QUOTATION SYMBOL_COMMENTSTART SYMBOL_COMMENTEND
	   KEYWORD_IDENTIFIER KEYWORD_INTEGER KEYWORD_REAL KEYWORD_STRING KEYWORD_PROGRAM
	   KEYWORD_IS KEYWORD_BEGIN KEYWORD_END KEYWORD_VAR KEYWORD_TYPE KEYWORD_PROCEDURE
	   KEYWORD_ARRAY KEYWORD_RECORD KEYWORD_IN KEYWORD_OUT KEYWORD_READ KEYWORD_WRITE
	   KEYWORD_IF KEYWORD_THEN KEYWORD_ELSE KEYWORD_ELSIF
	   KEYWORD_WHILE KEYWORD_DO KEYWORD_LOOP KEYWORD_FOR
	   KEYWORD_EXIT KEYWORD_RETURN KEYWORD_TO KEYWORD_BY
	   KEYWORD_AND KEYWORD_OR KEYWORD_NOT KEYWORD_OF KEYWORD_DIV KEYWORD_MOD

%token <Tstring> TYPE_INTEGER TYPE_REAL TYPE_STRING
%token <intConst> CONST_INTEGER
%token <doubleConst> CONST_REAL
%token <stringConst> CONST_STRING

%type <Tast> program
%type <Tast> Body
%type <Tast> Declarations
%type <Tast> Declaration
%type <Tast> VariableDeclaration
%type <Tast> TypeDeclaration
%type <Tast> ProcedureDeclaration
%type <Tast> Type
%type <Tast> Components
%type <Tast> Component
%type <Tast> FormalParameters
%type <Tast> FunctionParameterSections
%type <Tast> FunctionParameterSection
%type <Tast> Statements
%type <Tast> Statement
%type <Tast> IfStatement
%type <Tast> ForStatement
%type <Tast> ElsifStatements
%type <Tast> ElsifStatement
%type <Tast> WriteParameters
%type <Tast> WriteExpressions
%type <Tast> WriteExpression
%type <Tast> WriteContents
%type <Tast> Expressions
%type <Tast> Expression
%type <Tast> LeftValues
%type <Tast> LeftValue
%type <Tast> ActualParameters
%type <Tast> CompleteValues
%type <Tast> CompleteValue
%type <Tast> Array
%type <Tast> ArrayValues
%type <Tast> ArrayValue
%type <Tast> UnaryOperation
%type <Tast> BinaryOperation
%type <Tast> Identifiers
%type <Tast> Identifier

%left SYMBOL_PLUS SYMBOL_MINUS
%left SYMBOL_STAR SYMBOL_SLASH KEYWORD_DIV KEYWORD_MOD

%%

start: program                  { print_ast($1,0); }
     ;


program : KEYWORD_PROGRAM KEYWORD_IS Body SYMBOL_SEMICOLON {ast_list* temp=cons($3,NULL);$$=mk_node(program,temp);}
  //      | Comments KEYWORD_PROGRAM KEYWORD_IS Body SYMBOL_SEMICOLON {ast_list* temp=cons($4,NULL);temp=cons($1,temp);$$=mk_node(program,temp);}
        ;

Comments: Comment {;}
        | Comments Comment {;}
        ;

Comment : SYMBOL_COMMENTSTART CommentContents SYMBOL_COMMENTEND {;}
        | SYMBOL_COMMENTSTART SYMBOL_COMMENTEND {;}
        ;

CommentContents : CommentContent {;}
                | CommentContents CommentContent {;}
                ;

Body    : Declarations KEYWORD_BEGIN Statements KEYWORD_END{ast_list* temp=cons($3,NULL);temp=cons($1,temp);$$=mk_node(Body,temp);}
        | KEYWORD_BEGIN Statements KEYWORD_END{ast_list* temp=cons($2,NULL);$$=mk_node(Body,temp);}
        ;

Declarations    :   Declaration {ast_list* temp=cons($1,NULL);$$=mk_node(Declarations,temp);}
                |   Declaration Declarations {$2->info.node.arguments=cons($1,$2->info.node.arguments);$$=$2;}
                ;

Declaration :   KEYWORD_VAR VariableDeclaration {$$=$2;}
            |   KEYWORD_TYPE TypeDeclaration {$$=$2;}
            |   KEYWORD_PROCEDURE ProcedureDeclaration {$$=$2;}
	    ;

VariableDeclaration : Identifiers SYMBOL_ASSIGN Expression SYMBOL_SEMICOLON {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(VariableDeclaration,temp);}
                    | Identifiers SYMBOL_COLON Type SYMBOL_ASSIGN Expression SYMBOL_SEMICOLON {ast_list* temp=cons($5,NULL);cons($3,temp);cons($1,temp);$$=mk_node(VariableDeclaration,temp);}
                    ;

TypeDeclaration : Identifier KEYWORD_IS Type SYMBOL_SEMICOLON {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(TypeDeclaration,temp);}
                ;

ProcedureDeclaration    : Identifier FormalParameters KEYWORD_IS Body SYMBOL_SEMICOLON {ast_list* temp=cons($4,NULL);cons($2,temp);cons($1,temp);$$=mk_node(ProcedureDeclaration,temp);}
                        | Identifier FormalParameters SYMBOL_COLON Type KEYWORD_IS Body SYMBOL_SEMICOLON {ast_list* temp=cons($6,NULL);cons($4,temp);cons($2,temp);cons($1,temp);$$=mk_node(ProcedureDeclaration,temp);}
                        ;

Type    : TYPE_INTEGER {$$=mk_str(yytext);}
        | TYPE_REAL {$$=mk_str(yytext);}
        | TYPE_STRING {$$=mk_str(yytext);}
        | Identifier {$$=$1;}
        | KEYWORD_ARRAY KEYWORD_OF Type {ast_list* temp=cons($3,NULL);$$=mk_node(ArrayType,temp);}
        | KEYWORD_RECORD Components KEYWORD_END {ast_list* temp=cons($2,NULL);$$=mk_node(RecordType,temp);}
        ;

Components  : Component {ast_list* temp=cons($1,NULL);$$=mk_node(Components,temp);}
            | Component Components{$2->info.node.arguments=cons($1,$2->info.node.arguments);$$=$2;}
            ;

Component   : Identifier SYMBOL_COLON Type SYMBOL_SEMICOLON {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(Component,temp);}
            ;

FormalParameters    : SYMBOL_LPAREN SYMBOL_RPAREN {$$=mk_node(FormalParameters,NULL);}
                    | SYMBOL_LPAREN FunctionParameterSections SYMBOL_RPAREN {ast_list* temp=cons($2,NULL);$$=mk_node(FormalParameters,temp);}
                    ;

FunctionParameterSections   : FunctionParameterSection {ast_list* temp=cons($1,NULL);$$=mk_node(FunctionParameterSections,temp);}
                            | FunctionParameterSection SYMBOL_SEMICOLON FunctionParameterSections {$3->info.node.arguments=cons($1,$3->info.node.arguments);$$=$3;}
                            ;

FunctionParameterSection    : Identifiers SYMBOL_COLON Type {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(FunctionParameterSection,temp);}
                            ;

Statements  : Statement {ast_list* temp=cons($1,NULL);$$=mk_node(Statements,temp);}
            | Statement Statements {$2->info.node.arguments=cons($1,$2->info.node.arguments);$$=$2;}
            ;

Statement   : LeftValue SYMBOL_ASSIGN Expression SYMBOL_SEMICOLON {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(AssignmentStatement,temp);}
            | Identifier ActualParameters SYMBOL_SEMICOLON {ast_list* temp=cons($2,NULL);cons($1,temp);$$=mk_node(ProcedureCallStatement,temp);}
            | KEYWORD_READ SYMBOL_LPAREN LeftValues SYMBOL_RPAREN SYMBOL_SEMICOLON {ast_list* temp=cons($3,NULL);$$=mk_node(ReadStatement,temp);}
            | KEYWORD_WRITE WriteParameters SYMBOL_SEMICOLON {ast_list* temp=cons($2,NULL);$$=mk_node(WriteStatement,temp);}
            | IfStatement {$$=$1;}
            | KEYWORD_WHILE Expression KEYWORD_DO Statements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($4,NULL);cons($2,temp);$$=mk_node(WhileStatement,temp);}
            | KEYWORD_LOOP Statements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($2,NULL);$$=mk_node(LoopStatement,temp);}
            | ForStatement {$$=$1;}
            | KEYWORD_EXIT SYMBOL_SEMICOLON {$$=mk_node(ExitStatement,NULL);}
            | KEYWORD_RETURN SYMBOL_SEMICOLON {$$=mk_node(ReturnStatement,NULL);}
            | KEYWORD_RETURN Expression SYMBOL_SEMICOLON {ast_list* temp=cons($2,NULL);$$=mk_node(ReturnStatement,temp);}
            ;

IfStatement : KEYWORD_IF Expression KEYWORD_THEN Statements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($4,NULL);cons($2,temp);$$=mk_node(IfStatement,temp);}
            | KEYWORD_IF Expression KEYWORD_THEN Statements KEYWORD_ELSE Statements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($6,NULL);cons($4,temp);cons($2,temp);$$=mk_node(IfStatement,temp);}
            | KEYWORD_IF Expression KEYWORD_THEN Statements ElsifStatements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($5,NULL);cons($4,temp);cons($2,temp);$$=mk_node(IfStatement,temp);}
            | KEYWORD_IF Expression KEYWORD_THEN Statements ElsifStatements KEYWORD_ELSE Statements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($7,temp);cons($5,temp);cons($4,temp);cons($2,temp);$$=mk_node(IfStatement,temp);}
            ;

ForStatement    : KEYWORD_FOR Identifier SYMBOL_ASSIGN Expression KEYWORD_TO Expression KEYWORD_DO Statements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($8,NULL);cons($6,temp);cons($4,temp);cons($2,temp);$$=mk_node(ForStatement,temp);}
                | KEYWORD_FOR Identifier SYMBOL_ASSIGN Expression KEYWORD_TO Expression KEYWORD_BY Expression KEYWORD_DO Statements KEYWORD_END SYMBOL_SEMICOLON {ast_list* temp=cons($10,NULL);cons($8,temp);cons($6,temp);cons($4,temp);cons($2,temp);$$=mk_node(ForStatement,temp);}
                ;

ElsifStatements : ElsifStatement {ast_list* temp=cons($1,NULL);$$=mk_node(ElsifStatements,temp);}
                | ElsifStatement ElsifStatements {$2->info.node.arguments=cons($1,$2->info.node.arguments);$$=$2;}
                ;

ElsifStatement  : KEYWORD_ELSIF Expression KEYWORD_THEN Statements {ast_list* temp=cons($4,NULL);cons($2,temp);$$=mk_node(ElsifStatement,temp);}
                ;

WriteParameters : SYMBOL_LPAREN SYMBOL_RPAREN {$$=mk_node(WriteParameters,NULL);}
                | SYMBOL_LPAREN WriteExpressions SYMBOL_RPAREN {ast_list* temp=cons($2,NULL);$$=mk_node(WriteParameters,temp);}
                ;

WriteExpressions: WriteExpression {ast_list* temp=cons($1,NULL);$$=mk_node(WriteExpressions,temp);}
                | WriteExpression SYMBOL_COMMA WriteExpressions {$3->info.node.arguments=cons($1,$3->info.node.arguments);$$=$3;}
                ;

WriteExpression : SYMBOL_QUOTATION WriteContents SYMBOL_QUOTATION {ast_list* temp=cons($2,NULL);$$=mk_node(WriteExpression,temp);}
                | Expression {ast_list* temp=cons($1,NULL);$$=mk_node(WriteExpression,temp);}
                ;

WriteContents   : WriteContent {$$=mk_node(WriteContents,NULL);}
                | WriteContent WriteContents{$$=$2;}
                ;

Expressions : Expression {ast_list* temp=cons($1,NULL);$$=mk_node(Expressions,temp);}
            | Expression SYMBOL_COMMA Expressions {$3->info.node.arguments=cons($1,$3->info.node.arguments);$$=$3;}
	    ;

Expression  : CONST_INTEGER {ast* temp=mk_int(atoi(yytext));$$=mk_node(Expression,cons(temp,NULL));}
            | CONST_REAL {ast* temp=mk_real(atof(yytext));$$=mk_node(Expression,cons(temp,NULL));}
            | LeftValue {ast_list* temp=cons($1,NULL);$$=mk_node(Expression,temp);}
            | SYMBOL_LPAREN Expression SYMBOL_RPAREN {ast_list* temp=cons($2,NULL);$$=mk_node(Expression,temp);}
            | UnaryOperation Expression {ast_list* temp=cons($2,NULL);cons($1,temp);$$=mk_node(Expression,temp);}
            | Expression BinaryOperation Expression {ast_list* temp=cons($3,NULL);cons($2,temp);cons($1,temp);$$=mk_node(Expression,temp);}
            | Identifier ActualParameters {ast_list* temp=cons($2,NULL);cons($1,temp);$$=mk_node(Expression,temp);}
            | Identifier CompleteValues {ast_list* temp=cons($2,NULL);cons($1,temp);$$=mk_node(Expression,temp);}
            | Identifier Array {ast_list* temp=cons($2,NULL);cons($1,temp);$$=mk_node(Expression,temp);}
            ;

LeftValues  : LeftValue {ast_list* temp=cons($1,NULL);$$=mk_node(LeftValues,temp);}
            | LeftValue SYMBOL_COMMA LeftValues {$3->info.node.arguments=cons($1,$3->info.node.arguments);$$=$3;}
            ;

LeftValue   : Identifier {ast_list* temp=cons($1,NULL);$$=mk_node(LeftValue,temp);}
            | LeftValue SYMBOL_LBRACKET Expression SYMBOL_RBRACKET {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(LeftValue,temp);}
            | LeftValue SYMBOL_DOT Identifier {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(LeftValue,temp);}
            ;

ActualParameters    : SYMBOL_LPAREN Expressions SYMBOL_RPAREN {ast_list* temp=cons($2,NULL);$$=mk_node(ActualParameters,temp);}
                    | SYMBOL_LPAREN SYMBOL_RPAREN {$$=mk_node(ActualParameters,NULL);}
                    ;

CompleteValues  : CompleteValue {ast_list* temp=cons($1,NULL);$$=mk_node(CompleteValues,temp);}
                | CompleteValue SYMBOL_SEMICOLON CompleteValues {$3->info.node.arguments=cons($1,$3->info.node.arguments);$$=$3;}
                ;

CompleteValue   : SYMBOL_LBRACE Identifier SYMBOL_ASSIGN Expression SYMBOL_RBRACE {ast_list* temp=cons($4,NULL);cons($2,temp);$$=mk_node(CompleteValue,temp);}
                ;

Array   : SYMBOL_LABRACKET ArrayValues SYMBOL_RABRACKET {ast_list* temp=cons($2,NULL);$$=mk_node(Array,temp);}
        ;

ArrayValues : ArrayValue {ast_list* temp=cons($1,NULL);$$=mk_node(ArrayValues,temp);}
            | ArrayValue SYMBOL_COMMA ArrayValues {$3->info.node.arguments=cons($1,$3->info.node.arguments);$$=$3;}
            ;

ArrayValue  : Expression {ast_list* temp=cons($1,NULL);$$=mk_node(ArrayValue,temp);}
            | Expression KEYWORD_OF Expression {ast_list* temp=cons($3,NULL);cons($1,temp);$$=mk_node(ArrayValue,temp);}
            ;

UnaryOperation  : SYMBOL_PLUS {$$=mk_node(UnaryOperation,NULL);}
                | SYMBOL_MINUS {$$=mk_node(UnaryOperation,NULL);}
                | KEYWORD_NOT {$$=mk_node(UnaryOperation,NULL);}
                ;

BinaryOperation : SYMBOL_PLUS {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_MINUS {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_STAR {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_SLASH {$$=mk_node(BinaryOperation,NULL);}
                | KEYWORD_DIV {$$=mk_node(BinaryOperation,NULL);}
                | KEYWORD_MOD {$$=mk_node(BinaryOperation,NULL);}
                | KEYWORD_AND {$$=mk_node(BinaryOperation,NULL);}
                | KEYWORD_OR {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_LT {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_GT {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_LE {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_GE {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_NEQ {$$=mk_node(BinaryOperation,NULL);}
                | SYMBOL_EQ {$$=mk_node(BinaryOperation,NULL);}
                ;

Identifiers : Identifier {ast_list* temp=cons($1,NULL);$$=mk_node(Identifiers,temp);}
            | Identifier SYMBOL_COMMA Identifiers {$3->info.node.arguments=cons($1,$3->info.node.arguments);$$=$3;}
            ;

Identifier  : CONST_STRING {$$=mk_node(Identifier,NULL);}

WriteContent                :   CONST_INTEGER {;}
                            |   CONST_REAL {;}
                            |   CONST_STRING {;}
                            |   SYMBOL_LPAREN {;}
                            |   SYMBOL_RPAREN {;}
                            |   SYMBOL_LBRACKET {;}
                            |   SYMBOL_RBRACKET {;}
                            |   SYMBOL_LBRACE {;}
                            |   SYMBOL_RBRACE {;}
                            |   SYMBOL_COLON {;}
                            |   SYMBOL_DOT {;}
                            |   SYMBOL_SEMICOLON {;}
                            |   SYMBOL_COMMA {;}
                            |   SYMBOL_ASSIGN {;}
                            |   SYMBOL_PLUS {;}
                            |   SYMBOL_MINUS {;}
                            |   SYMBOL_STAR {;}
                            |   SYMBOL_SLASH {;}
                            |   SYMBOL_BACKSLASH {;}
                            |   SYMBOL_EQ {;}
                            |   SYMBOL_NEQ {;}
                            |   SYMBOL_LT {;}
                            |   SYMBOL_LE {;}
                            |   SYMBOL_GT {;}
                            |   SYMBOL_GE {;}
                            |   SYMBOL_LABRACKET {;}
                            |   SYMBOL_RABRACKET {;}
                            |   KEYWORD_IDENTIFIER {;}
                            |   KEYWORD_INTEGER {;}
                            |   KEYWORD_REAL {;}
                            |   KEYWORD_STRING {;}
                            |   KEYWORD_PROGRAM {;}
                            |   KEYWORD_IS {;}
                            |   KEYWORD_BEGIN {;}
                            |   KEYWORD_END {;}
                            |   KEYWORD_VAR {;}
                            |   KEYWORD_TYPE {;}
                            |   KEYWORD_PROCEDURE {;}
                            |   KEYWORD_ARRAY {;}
                            |   KEYWORD_RECORD {;}
                            |   KEYWORD_IN {;}
                            |   KEYWORD_OUT {;}
                            |   KEYWORD_READ {;}
                            |   KEYWORD_WRITE {;}
                            |   KEYWORD_IF {;}
                            |   KEYWORD_THEN {;}
                            |   KEYWORD_ELSE {;}
                            |   KEYWORD_ELSIF {;}
                            |   KEYWORD_WHILE {;}
                            |   KEYWORD_DO {;}
                            |   KEYWORD_LOOP {;}
                            |   KEYWORD_FOR {;}
                            |   KEYWORD_EXIT {;}
                            |   KEYWORD_RETURN {;}
                            |   KEYWORD_TO {;}
                            |   KEYWORD_BY {;}
                            |   KEYWORD_AND {;}
                            |   KEYWORD_OR {;}
                            |   KEYWORD_NOT {;}
                            |   KEYWORD_OF {;}
                            |   KEYWORD_DIV {;}
                            |   KEYWORD_MOD {;}
                            |   TYPE_INTEGER {;}
                            |   TYPE_REAL {;}
                            |   TYPE_STRING {;}
                            ;

CommentContent              :   CONST_INTEGER {;}
                            |   CONST_REAL {;}
                            |   CONST_STRING {;}
                            |   SYMBOL_LPAREN {;}
                            |   SYMBOL_RPAREN {;}
                            |   SYMBOL_LBRACKET {;}
                            |   SYMBOL_RBRACKET {;}
                            |   SYMBOL_LBRACE {;}
                            |   SYMBOL_RBRACE {;}
                            |   SYMBOL_COLON {;}
                            |   SYMBOL_DOT {;}
                            |   SYMBOL_SEMICOLON {;}
                            |   SYMBOL_COMMA {;}
                            |   SYMBOL_ASSIGN {;}
                            |   SYMBOL_PLUS {;}
                            |   SYMBOL_MINUS {;}
                            |   SYMBOL_STAR {;}
                            |   SYMBOL_SLASH {;}
                            |   SYMBOL_BACKSLASH {;}
                            |   SYMBOL_EQ {;}
                            |   SYMBOL_NEQ {;}
                            |   SYMBOL_LT {;}
                            |   SYMBOL_LE {;}
                            |   SYMBOL_GT {;}
                            |   SYMBOL_GE {;}
                            |   SYMBOL_LABRACKET {;}
                            |   SYMBOL_RABRACKET {;}
                            |   KEYWORD_IDENTIFIER {;}
                            |   KEYWORD_INTEGER {;}
                            |   KEYWORD_REAL {;}
                            |   KEYWORD_STRING {;}
                            |   KEYWORD_PROGRAM {;}
                            |   KEYWORD_IS {;}
                            |   KEYWORD_BEGIN {;}
                            |   KEYWORD_END {;}
                            |   KEYWORD_VAR {;}
                            |   KEYWORD_TYPE {;}
                            |   KEYWORD_PROCEDURE {;}
                            |   KEYWORD_ARRAY {;}
                            |   KEYWORD_RECORD {;}
                            |   KEYWORD_IN {;}
                            |   KEYWORD_OUT {;}
                            |   KEYWORD_READ {;}
                            |   KEYWORD_WRITE {;}
                            |   KEYWORD_IF {;}
                            |   KEYWORD_THEN {;}
                            |   KEYWORD_ELSE {;}
                            |   KEYWORD_ELSIF {;}
                            |   KEYWORD_WHILE {;}
                            |   KEYWORD_DO {;}
                            |   KEYWORD_LOOP {;}
                            |   KEYWORD_FOR {;}
                            |   KEYWORD_EXIT {;}
                            |   KEYWORD_RETURN {;}
                            |   KEYWORD_TO {;}
                            |   KEYWORD_BY {;}
                            |   KEYWORD_AND {;}
                            |   KEYWORD_OR {;}
                            |   KEYWORD_NOT {;}
                            |   KEYWORD_OF {;}
                            |   KEYWORD_DIV {;}
                            |   KEYWORD_MOD {;}
                            |   TYPE_INTEGER {;}
                            |   TYPE_REAL {;}
                            |   TYPE_STRING {;}
                            ;

%%
